package com.njcb.ams.service;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.njcb.ams.support.annotation.AmsConfigDefault;
import com.njcb.ams.util.AmsAssert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.njcb.ams.repository.dao.CommOrgInfoDAO;
import com.njcb.ams.repository.dao.CommRoleInfoDAO;
import com.njcb.ams.repository.dao.CommUserInfoDAO;
import com.njcb.ams.repository.entity.CommOrgInfo;
import com.njcb.ams.repository.entity.CommRoleInfo;
import com.njcb.ams.repository.entity.CommRoleInfoExample;
import com.njcb.ams.repository.entity.CommUserInfo;
import com.njcb.ams.factory.domain.AppContext;
import com.njcb.ams.portal.SysBaseDefine;
import com.njcb.ams.support.security.bo.LoginModel;
import com.njcb.ams.support.security.bo.SecurityUser;
import com.njcb.ams.support.security.config.AmsSecurityConfiguration;
import com.njcb.ams.util.SysInfoUtils;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;

@AmsConfigDefault
public class SecurityConfiguration implements AmsSecurityConfiguration {

	@Autowired
	private CommUserInfoDAO commUserInfoDAO;
	@Autowired
	private CommRoleInfoDAO commRoleInfoDAO;
	@Autowired
	private CommOrgInfoDAO commOrgInfoDAO;
	
	@Override
	public SecurityUser loadUserByUsername(String loginName, String authCode, Map<String, Object> param, Boolean isLogin) {
		SecurityUser securityUser = new SecurityUser();
		//授权码模式
		if(LoginModel.AUTHCODE.equals(loginModel())){
			//需要到第三方验证授权码loginCode
			//暂不支持
			securityUser.setId(1);
			securityUser.setLoginName(loginName);
			securityUser.setUserName(loginName);
			securityUser.setPassWord(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode(loginName));
			securityUser.setBusiDate(SysInfoUtils.getBusiDate());
			return securityUser;
		}
		CommUserInfo userInfo = commUserInfoDAO.findSecurityUserByLoginName(loginName);
		if (userInfo == null) {
			throw new UsernameNotFoundException("用户[" + loginName + "]不存在");
		}else if(SysBaseDefine.STATUS_INVALID.equals(userInfo.getStatus())){
			throw new AccountExpiredException("用户[" + loginName + "]状态无效");
		}
		List<Integer> roleIds = commUserInfoDAO.getMapper().selectRoleIdsByUserId(userInfo.getId());
		if(roleIds.size() > 0){
			CommRoleInfoExample example = new CommRoleInfoExample();
			example.createCriteria().andIdIn(roleIds);
			List<CommRoleInfo> roleList = commRoleInfoDAO.selectByExample(example);
			userInfo.setRoleList(roleList);
		}else{
			userInfo.setRoleList(new ArrayList<CommRoleInfo>());
		}
		
		CommOrgInfo commOrgInfo = commOrgInfoDAO.selectByPrimaryKey(userInfo.getOrgId());
		AmsAssert.notNull(commOrgInfo,"用户所属机构不存在");
		securityUser.setId(userInfo.getId());
		securityUser.setRoleCodes(userInfo.getRoleList().stream().map(CommRoleInfo::getRoleCode).collect(Collectors.toList()));
		securityUser.setLoginName(userInfo.getLoginName());
		securityUser.setUserName(userInfo.getUserName());
		securityUser.setPassWord(userInfo.getPassWord());
		securityUser.setOrgnNo(commOrgInfo.getOrgNo());
		securityUser.setOrgnName(commOrgInfo.getOrgName());
		securityUser.setBusiDate(SysInfoUtils.getBusiDate());
		securityUser.setEmpNo(userInfo.getEmpNo());
		return securityUser;
	}
	
	@Override
	public LoginModel loginModel() {
		return LoginModel.PASSWORD;
	}
	
	@Override
	public void permitMatchers(List<String> antPatterns) {
		antPatterns.add("/register");
		antPatterns.add("/index/register");
		antPatterns.add("/index/param");
		antPatterns.add("/html/**");
		antPatterns.add("/js/**");
		antPatterns.add("/css/**");
		antPatterns.add("/images/**");
		antPatterns.add("/health/**");
	}

	
	public static void main(String[] args) throws Exception {
		Object bean = Class.forName("com.njcb.ams.service.SecurityConfiguration").newInstance();
		Field[] fields = bean.getClass().getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);
			field.set(bean, AppContext.getBean(""));
		}
		System.out.println(bean);
		System.out.println(bean);
	}
}
